﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Drawing.Drawing2D;

namespace ScreenShark.Controls
{
    public class SelectablePictureBox : PictureBox
    {
        private Point fDownPoint = Point.Empty;
        private Point fCurrentPoint = Point.Empty;

        private enum SelectionState
        {
            Nothing,
            BeginSelect,
            Selecting,
            Selected
        }

        private SelectionState fSelState = SelectionState.Nothing;

        [Browsable(false)]        
        public Rectangle SelectedRectangle
        {
            get
            {
                if (!HasSelectedRectangle)
                    return Rectangle.Empty;

                int x = Math.Min(fDownPoint.X, fCurrentPoint.X);
                int y = Math.Min(fDownPoint.Y, fCurrentPoint.Y);
                int width = Math.Abs(fCurrentPoint.X - fDownPoint.X);
                int height = Math.Abs(fCurrentPoint.Y - fDownPoint.Y);

                return new Rectangle(x, y, width, height);
            }
        }
        
        [Browsable(false)] 
        public bool HasSelectedRectangle
        {
            get
            {
                return fSelState == SelectionState.Selecting || fSelState == SelectionState.Selected;
            }
        }

        public Image GetSelectedImage()
        {
            if (!HasSelectedRectangle) return null;

            Bitmap b = new Bitmap(SelectedRectangle.Width, SelectedRectangle.Height);
            Graphics g = Graphics.FromImage(b);
            g.DrawImage(Image, 0, 0, SelectedRectangle, GraphicsUnit.Pixel);
            g.Dispose();
            return b;
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);

            if (HasSelectedRectangle)
            {
                using (var b = new SolidBrush(Color.FromArgb(128,Color.Black)))
                {
                    pe.Graphics.SetClip(SelectedRectangle, CombineMode.Exclude);
                    pe.Graphics.FillRectangle(b, ClientRectangle);                    
                }
            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {            
            fDownPoint = fCurrentPoint = Point.Empty;

            if (e.Button == MouseButtons.Left)
            {
                fDownPoint = e.Location;
                
                fSelState = SelectionState.BeginSelect;

                Cursor = Cursors.SizeAll;
            }
   
            base.OnMouseDown(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {           
            if (e.Button == MouseButtons.Left && e.Location != fDownPoint)
            {
                fCurrentPoint = e.Location;

                if (fCurrentPoint.X < ClientRectangle.Left)
                    fCurrentPoint.X = ClientRectangle.Left;
                else if (fCurrentPoint.X > ClientRectangle.Right)
                    fCurrentPoint.X = ClientRectangle.Right;

                if (fCurrentPoint.Y < ClientRectangle.Top)
                    fCurrentPoint.Y = ClientRectangle.Top;
                else if (fCurrentPoint.Y > ClientRectangle.Bottom)
                    fCurrentPoint.Y = ClientRectangle.Bottom;

                fSelState = SelectionState.Selecting;
            }

            base.OnMouseMove(e);

            Invalidate();
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            if (e.Button == MouseButtons.Right)
            {
                fSelState = SelectionState.Nothing;
                Invalidate();
            }
            else if (fSelState == SelectionState.Nothing)
            {
                fSelState = SelectionState.Selected;
            }

            Cursor = Cursors.Default;
        }
    }
}
